#include <iostream>
#include "Player.h"
#include "CatanClassContractException.h"

namespace catan
{

Player::Player():availableResources(){
	playerName		= "none";
	playerColor		= RED;
	victoryPoints	= 0;
	nmbOfRoadsLeft		= 0;
	nmbOfSettlementsLeft = 0;
	nmbOfCitiesLeft		= 0;
	nmbOfRoadsPlaced		= 0;
	nmbOfSettlementsPlaced = 0;
	nmbOfCitiesPlaced		= 0;
	std::vector<DevelopmentCard::Enum_DevelopmentCard> possibleDevelopmentCards = DevelopmentCard::getVectorOfPossibleEnumValues();
	for (std::vector<DevelopmentCard::Enum_DevelopmentCard>::const_iterator possibleDevelopmentCardIterator = possibleDevelopmentCards.begin(); possibleDevelopmentCardIterator != possibleDevelopmentCards.end(); possibleDevelopmentCardIterator++)
	{
		privateDevelopments.insert(std::make_pair(*possibleDevelopmentCardIterator, 0));
		onTableDevelopments.insert(std::make_pair(*possibleDevelopmentCardIterator, 0));
	}
}

Player::Player(std::string theName, color theColor): availableResources(){
	victoryPoints	= 0;
	nmbOfRoadsLeft		= 15;
	nmbOfSettlementsLeft = 5;
	nmbOfCitiesLeft		= 4;
	nmbOfRoadsPlaced		= 0;
	nmbOfSettlementsPlaced = 0;
	nmbOfCitiesPlaced		= 0;
	playerName		= theName;
	playerColor		= theColor;
	colorRed = 1.0f;
	colorGreen = 0.0f;
	colorBlue = 0.0f;
	std::vector<DevelopmentCard::Enum_DevelopmentCard> possibleDevelopmentCards = DevelopmentCard::getVectorOfPossibleEnumValues();
	for (std::vector<DevelopmentCard::Enum_DevelopmentCard>::const_iterator possibleDevelopmentCardIterator = possibleDevelopmentCards.begin(); possibleDevelopmentCardIterator != possibleDevelopmentCards.end(); possibleDevelopmentCardIterator++)
	{
		privateDevelopments.insert(std::make_pair(*possibleDevelopmentCardIterator, 0));
		onTableDevelopments.insert(std::make_pair(*possibleDevelopmentCardIterator, 0));
	}
}

//modified here
#ifdef Claudiu
Player::Player(std::string theName, float theRed, float theGreen, float theBlue): availableResources(10,10,10,10,10){
#else
Player::Player(std::string theName, float theRed, float theGreen, float theBlue): availableResources(0, 0, 0, 0, 0){
#endif
	victoryPoints	= 0;
	nmbOfRoadsLeft		= 15;
	nmbOfSettlementsLeft = 5;
	nmbOfCitiesLeft		= 4;
	nmbOfRoadsPlaced		= 0;
	nmbOfSettlementsPlaced = 0;
	nmbOfCitiesPlaced		= 0;
	playerName		= theName;
	colorRed		= theRed;
	colorGreen		= theGreen;
	colorBlue		= theBlue;
	playerColor = RED;
	std::vector<DevelopmentCard::Enum_DevelopmentCard> possibleDevelopmentCards = DevelopmentCard::getVectorOfPossibleEnumValues();
	for (std::vector<DevelopmentCard::Enum_DevelopmentCard>::const_iterator possibleDevelopmentCardIterator = possibleDevelopmentCards.begin(); possibleDevelopmentCardIterator != possibleDevelopmentCards.end(); possibleDevelopmentCardIterator++)
	{
		privateDevelopments.insert(std::make_pair(*possibleDevelopmentCardIterator, 0));
		onTableDevelopments.insert(std::make_pair(*possibleDevelopmentCardIterator, 0));
	}
}

int Player::getVictoryPoints(bool largestArmy, bool longestRoad){
	return victoryPoints+(largestArmy?1:0)*2+(longestRoad?1:0)*2;
}

int Player::getNmbOfRoadsLeft(){
	return nmbOfRoadsLeft;
}

int Player::getNmbOfSettlementsLeft(){
	return nmbOfSettlementsLeft;
}

int Player::getNmbOfCitiesLeft(){
	return nmbOfCitiesLeft;
}

int Player::getNmbOfRoadsPlaced(){
	return nmbOfRoadsPlaced;
}

int Player::getNmbOfSettlementsPlaced(){
	return nmbOfSettlementsPlaced;
}

int Player::getNmbOfCitiesPlaced(){
	return nmbOfCitiesPlaced;
}

std::string Player::getName(){
	return playerName;
}

color Player::getColor(){
	return playerColor;
}

float Player::getRed(){
	return colorRed;
}

float Player::getGreen(){
	return colorGreen;
}

float Player::getBlue(){
	return colorBlue;
}

ResourceSet Player::getResources(){
	return availableResources;
}

const std::map<DevelopmentCard, int> &Player::getPrivateDevelopments(){
	return privateDevelopments;
}

const std::map<DevelopmentCard, int> &Player::getOnTableDevelopments(){
	return onTableDevelopments;
}

void Player::setVictoryPoints(int theNumber){
	victoryPoints = theNumber;
}

void Player::addRoad(PathCoordinate pathCoordinate)
{
	--nmbOfRoadsLeft;
	++nmbOfRoadsPlaced;
	roadCoordinates.push_back(pathCoordinate);
	if (nmbOfRoadsPlaced > 2)
	{
		availableResources = availableResources - catan::roadCost;
	}
}

std::vector<PathCoordinate> Player::getRoads()
{
	return roadCoordinates;
}

void Player::addSettlement(SiteCoordinate siteCoordinate)
{
	--nmbOfSettlementsLeft;
	++nmbOfSettlementsPlaced;
	victoryPoints += catan::VP_SETTLEMENT;
	settlementCoordinates.push_back(siteCoordinate);
	if (nmbOfSettlementsPlaced > 2)
	{
		availableResources = availableResources - catan::settlementCost;
	}
}

std::vector<SiteCoordinate> Player::getSettlements()
{
	return settlementCoordinates;
}

void Player::upgradeSettlement(SiteCoordinate siteCoordinate)
{
	std::vector<SiteCoordinate> newSettlementCoordinates;
	for (std::vector<SiteCoordinate>::const_iterator siteCoordinateIterator = settlementCoordinates.begin(); siteCoordinateIterator != settlementCoordinates.end(); ++siteCoordinateIterator)
	{
		if (!(siteCoordinate == *siteCoordinateIterator))
		{
			newSettlementCoordinates.push_back(*siteCoordinateIterator);				
		}
	}
	settlementCoordinates = newSettlementCoordinates;
	cityCoordinates.push_back(siteCoordinate);
	++nmbOfSettlementsLeft;
	--nmbOfSettlementsPlaced;
	--nmbOfCitiesLeft;
	++nmbOfCitiesPlaced;
	victoryPoints += catan::VP_CITY;
	availableResources = availableResources - catan::cityCost;
}

std::vector<SiteCoordinate> Player::getCities()
{
	return cityCoordinates;
}

void Player::setResources(ResourceSet newAvailableResources){
	availableResources = newAvailableResources;
}

void Player::addDevelopmentCard(DevelopmentCard developmentCard){
	privateDevelopments.find(developmentCard)->second++;
	availableResources = availableResources - catan::developmentCost;
}

bool Player::canPlayDevelopmentCard(DevelopmentCard developmentCard)
{
	return privateDevelopments.find(developmentCard)->second > 0;
}

void Player::playDevelopmentCard(DevelopmentCard developmentCard){
	privateDevelopments.find(developmentCard)->second--;
	onTableDevelopments.find(developmentCard)->second++;
	if(developmentCard == catan::monopolyCard || developmentCard == catan::roadBuildingCard || developmentCard == catan::yearOfPlentyCard || developmentCard == catan::soldierCard)
		// do the action for these cards that will not be taken into account for victory points
		std::cout<<"development card:"<<developmentCard.getEnum()<<" played"<<std::endl;
	else
		victoryPoints += catan::VP_DEVELOPMENT;
}

void Player::printPlayer(){
	std::string stringColor;
	switch(playerColor){
	case 0:
		stringColor = "red";
		break;
	case 1:
		stringColor = "green";
		break;
	case 2:
		stringColor = "blue";
		break;
	case 3:
		stringColor = "yellow";
		break;
	default:
		stringColor = "undefined color";
	}
	std::cout<<"name: "<<playerName<<", color: "<<stringColor<<", victory points: "<<victoryPoints<<std::endl;
	availableResources.printResourceSet();
	std::cout<<"in hand [removedfromcode]" << std::endl;
	std::cout<<"on table [removedfromcode]" << std::endl;
	std::cout<<"Available to buy roads: "<<nmbOfRoadsLeft<<", settlements: "<<nmbOfSettlementsLeft<<", cities: "<< nmbOfCitiesLeft<<std::endl;
}

}
